using FastDevTemplate.Api.Attribute;
using FastDevTemplate.Api.Model.Base;
using FastDevTemplate.Common.Util;
using FastDevTemplate.Service;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace FastDevTemplate.Api.Filter;

public class ApiPermissionVerificationFilter : IAsyncActionFilter
{
    private readonly IConfiguration _configuration;

    public ApiPermissionVerificationFilter(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        //before:
        var actionAttribute = context.ActionDescriptor.EndpointMetadata
            .OfType<PermissionVerificationAttribute>()
            .FirstOrDefault();

        if (actionAttribute != null && !CheckWhitelist(context, actionAttribute))
        {
            var token = context.HttpContext.Request.Headers["token"].FirstOrDefault();
            var uuid = context.HttpContext.Request.Headers["uuid"].FirstOrDefault();

            if (token == null || uuid == null)
            {
                context.Result = new OkObjectResult(GetErrorResult(ErrorType.BaseError));
                return;
            }

            if (!Guid.TryParse(uuid, out var userid))
            {
                context.Result = new OkObjectResult(GetErrorResult(ErrorType.BaseError));
                return;
            }

            var loginInfo = TokenService.TryGetToken(userid);

            if(loginInfo == null || loginInfo.Token != token)
            {
                context.Result = new OkObjectResult(GetErrorResult(ErrorType.LogicTokenError));
                return;
            }
            
            if (!string.IsNullOrEmpty(actionAttribute.ID))
                if (!loginInfo.UserLoginDto.UserRoles.Any(item => item.PermissionIDs.Contains(actionAttribute.ID)))
                {
                    context.Result = new OkObjectResult(GetErrorResult(ErrorType.BaseError));
                    return;
                }
        }

        await next();
        //after:
    }

    private bool CheckWhitelist(ActionExecutingContext context, PermissionVerificationAttribute attribute)
    {
        if (!attribute.UseWhitelist)
            return false;
        var ipAddress = context.HttpContext.Connection.RemoteIpAddress?.MapToIPv4()?.ToString();
        var ipWhitelist = _configuration.GetSection("Whitelist").Get<string[]>();
        return ipWhitelist?.Contains(ipAddress) ?? false;
    }

    private static HttpResult<object> GetErrorResult(ErrorType errorType)
    {
        return new HttpResult<object>
        {
            Code = (int)errorType
        };
    }
}